﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web;
using System.Security.Permissions;

namespace Accumulation.Controls.Paginations {
    /// <summary>
    /// 分页控件
    /// </summary>
    [
    DefaultProperty("PageStyle"),
    ParseChildren(true),
    ToolboxData("<{0}:Paginations runat=server></{0}:Paginations>"),
    AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)
    ]
    public class Paginations : Control, INamingContainer, IPostBackEventHandler {

        #region Variables

        private int _recordCount = 0, _pageIndex = 1, _pageNumIndex = 1;
        private int _pageSize = 10, _pageNumSize = 10, _pageIndexPreNum = 2;

        #endregion        

        #region Property

        /// <summary>
        /// 分页样式
        /// </summary>
        [Description("分页样式")]
        public PageStyleEnums PageStyle { get; set; }
        /// <summary>
        /// Url，MVC 链接的时候带上完整的路径，例：http://localhost/View/List/{0}/{1}，{0}表示当前页，{1}表示当前翻页
        /// </summary>
        [Description("Url，MVC 链接的时候带上完整的路径，例：http://localhost/View/List/{0}/{1}，{0}表示当前页，{1}表示当前翻页")]
        public string Url { get; set; }
        /// <summary>
        /// 分页链接类型
        /// </summary>
        [Description("分页链接类型")]
        public LinkTypeEnums LinkType { get; set; }
        /// <summary>
        /// 总记录数
        /// </summary>
        [Description("总记录数"), Browsable(false)]
        public int RecordCount {
            get { return this._recordCount; }
            set {
                if (value < 0) {
                    throw new Exception("总记录数必须大于等于 0");
                }
                this._recordCount = value;
            }
        }
        /// <summary>
        /// 每页显示记录数
        /// </summary>
        [Description("每页显示记录数"), DefaultValue(10)]
        public int PageSize {
            get { return this._pageSize; }
            set {
                if (value <= 0) {
                    throw new Exception("每页显示记录数必须大于 0");
                }
                this._pageSize = value; 
            }
        }
        /// <summary>
        /// 每一页显示页码链接数量，并不是每一种分页形式都会用到
        /// </summary>
        [Description("每一页显示页码链接数量，并不是每一种分页形式都会用到"), DefaultValue(10)]
        public int PageNumSize {
            get { return this._pageNumSize; }
            set {
                if (this.PageStyle == PageStyleEnums.Three && value <= 0) {
                    throw new Exception("每一页显示页码链接数量必须大于 0");
                }
                this._pageNumSize = value;
            }
        }
        /// <summary>
        /// 总页数
        /// </summary>
        [Description("总页数"), Browsable(false)]
        public int PageCount {
            get { return Helper.GetPageCount(this.RecordCount, this.PageSize); }
        }
        /// <summary>
        /// 总翻页数
        /// </summary>
        [Description("总翻页数"), Browsable(false)]
        public int PageNumCount {
            get { return Helper.GetPageNumCount(this.PageCount, this.PageNumSize); }
        }
        /// <summary>
        /// 当前页码
        /// </summary>
        [Description("当前页码"), Browsable(false)]
        public int PageIndex {
            get {
                switch (this.LinkType) {
                    case LinkTypeEnums.Url:
                        return Helper.GetCurrentPage(this.PageQueryString, this.PageCount);
                    case LinkTypeEnums.Mvc:
                        return Helper.GetCurrentPage(this._pageIndex, this.PageCount);
                    case LinkTypeEnums.Postback:
                        return Helper.GetCurrentPage(this._pageIndex, this.PageCount);
                    default:
                        return this._pageIndex;
                }
            }
            set {
                if (value <= 0) {
                    throw new Exception("当前页码必须大于 0");
                }
                this._pageIndex = value;
            }
        }
        /// <summary>
        /// 当前翻页页码
        /// </summary>
        [Description("当前翻页页码"), Browsable(false)]
        public int PageNumIndex {
            get {
                switch (this.LinkType) {
                    case LinkTypeEnums.Url:
                        return Helper.GetCurrentPage(this.PageNumQueryString, this.PageNumCount);
                    case LinkTypeEnums.Mvc:
                        return Helper.GetCurrentPage(this._pageNumIndex, this.PageNumCount);
                    case LinkTypeEnums.Postback:
                        return Helper.GetCurrentPage(this._pageNumIndex, this.PageNumCount);
                    default:
                        return this._pageNumIndex;
                }
            }
            set {
                if (this.PageStyle == PageStyleEnums.Three && value <= 0) {
                    throw new Exception("当前翻页页码必须大于 0");
                }
                this._pageNumIndex = value;
            }
        }
        /// <summary>
        /// 当前页码前显示页数
        /// </summary>
        [Description("当前页码前显示页数"), DefaultValue(2)]
        public int PageIndexPreNum {
            get { return this._pageIndexPreNum; }
            set { this._pageIndexPreNum = value < 0 || value >= this._pageNumSize ? 2 : value; }
        }
        /// <summary>
        /// 分页页码查询字符串
        /// </summary>
        [Description("分页页码查询字符串"), Browsable(false)]
        public string PageQueryString {
            get { return Helper.GetQueryStringPage(this.ClientID); }
        }
        /// <summary>
        /// 分页翻页页码查询字符串
        /// </summary>
        [Description("分页翻页页码查询字符串"), Browsable(false)]
        public string PageNumQueryString {
            get { return Helper.GetQueryStringPageNum(this.ClientID); }
        }

        #endregion

        #region ControlState

        /// <summary>
        /// 注册ControlState状态
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e) {
            base.OnInit(e);
            Page.RegisterRequiresControlState(this);
        }
        /// <summary>
        /// 保存ControlState
        /// </summary>
        /// <returns></returns>
        protected override object SaveControlState() {
            List<object> scs = new List<object>();
            scs.Add(_pageIndex);
            scs.Add(_pageSize);
            scs.Add(_pageNumIndex);
            scs.Add(_pageNumSize);
            scs.Add(_recordCount);
            scs.Add(_pageIndexPreNum);
            scs.Add(this.Url);
            scs.Add(this.LinkType);
            scs.Add(this.PageStyle);
            return scs;
        }
        /// <summary>
        /// 载入ControlState
        /// </summary>
        /// <param name="savedState"></param>
        protected override void LoadControlState(object savedState) {
            if (savedState != null) {
                List<object> scs = savedState as List<object>;
                if (scs != null) {
                    _pageIndex = (int)scs[0];
                    _pageSize = (int)scs[1];
                    _pageNumIndex = (int)scs[2];
                    _pageNumSize = (int)scs[3];
                    _recordCount = (int)scs[4];
                    _pageIndexPreNum = (int)scs[5];
                    this.Url = (string)scs[6];
                    this.LinkType = (LinkTypeEnums)scs[7];
                    this.PageStyle = (PageStyleEnums)scs[8];
                }
            }

        }

        #endregion       

        /// <summary>
        /// 重画
        /// </summary>
        /// <param name="e">EventArgs</param>
        protected override void OnPreRender(EventArgs e) {
            HtmlLink hl = new HtmlLink();
            hl.Href = Helper.GetWebResourceUrl("Accumulation.Controls.Paginations.Paginations.css", this);
            hl.Attributes.Add("rel", "stylesheet");
            hl.Attributes.Add("type", "text/css");
            hl.ID = "Css_Paginations";
            if (this.Page.Header.FindControl("Css_Paginations") == null) {
                this.Page.Header.Controls.Add(hl);
            }

            this.Page.ClientScript.RegisterClientScriptInclude("PaginationsFile",
                Helper.GetWebResourceUrl("Accumulation.Controls.Paginations.Paginations.js", this));

            base.OnPreRender(e);
        }
        /// <summary>
        /// 绘出
        /// </summary>
        /// <param name="writer">HtmlTextWriter</param>
        protected override void Render(HtmlTextWriter writer) {
            if (this.DesignMode) this.EnsureChildControls();
            if (this.Visible) {
                switch (this.LinkType) {
                    case LinkTypeEnums.Url:
                        this.Url = Helper.GetUrl(this.PageQueryString);
                        if (this.PageStyle == PageStyleEnums.Three) {
                            this.Url = Helper.GetUrl(this.PageQueryString, this.PageNumQueryString);
                        }
                        break;
                    case LinkTypeEnums.Mvc:
                        if (string.IsNullOrEmpty(this.Url)) {
                            throw new Exception("MVC 的时候必须提供 Url");
                        }
                        break;
                    case LinkTypeEnums.Postback:
                        this.Url = string.Empty;
                        break;
                }
                var pp = new PageParameters {
                    Writer = writer,
                    PageObject = this.Page,
                    ControlObject = this,
                    Url = this.Url,
                    LinkType = this.LinkType,
                    RecordCount = this.RecordCount,
                    PageSize = this.PageSize,
                    PageNumSize = this.PageNumSize,
                    PageCount = this.PageCount,
                    PageNumCount = this.PageNumCount,
                    PageIndex = this.PageIndex,
                    PageNumIndex = this.PageNumIndex,
                    PageIndexPreNum = this.PageIndexPreNum 
                };
                switch (this.PageStyle) {
                    case PageStyleEnums.One: Helper.OutputPageOne(pp); break;
                    case PageStyleEnums.Two: Helper.OutputPageTwo(pp); break;
                    case PageStyleEnums.Three: Helper.OutputPageThree(pp); break;
                    case PageStyleEnums.Four: Helper.OutputPageFour(pp); break;
                    case PageStyleEnums.Five: Helper.OutputPageFive(pp); break;
                }
            }
        }

        #region Events

        /// <summary>
        /// 
        /// </summary>
        [Description("Paginations_OnPaging"), Category("Action")]
        public event PageEventHandler Paging {
            add { base.Events.AddHandler("Paging", value); }
            remove { base.Events.RemoveHandler("Paging", value); }
        }
        /// <summary>
        /// 分页事件
        /// </summary>
        /// <param name="sender">分页控件</param>
        /// <param name="e">分页事件参数</param>
        protected virtual void OnPaging(object sender, PaginationsEventArgs e) {
            PageEventHandler handler = (PageEventHandler)base.Events["Paging"];
            if (handler != null) {
                handler(sender, e);
            }
        }
        /// <summary>
        /// 引发事件
        /// </summary>
        /// <param name="eventArgument">事件回发参数</param>
        public void RaisePostBackEvent(string eventArgument) {
            this.PageIndex = 1;
            this.PageNumIndex = 1;
            if (this.PageStyle == PageStyleEnums.Three) {
                string[] values = eventArgument.Split('$');                
                this.PageIndex = int.Parse(values[0]);
                this.PageNumIndex = int.Parse(values[1]);
            }
            else {
                this.PageIndex = int.Parse(eventArgument);
                this.PageNumIndex = 1;
            }
            this.OnPaging(this, new PaginationsEventArgs(this.PageIndex, this.PageNumIndex));
        }

        #endregion
    }
}
